//******************************************************************************
//  RCR Test Sandbox
//
//	Added open/close simulation. Motor will 'close' until 
//	P1.4 goes high at which point it 'opens' for MAXSTEPS 
//	steps. When MAXSTEPS is reached, motor 'closes' again 
//	and cycle repeats.
//
//           MSP430G2231
//         ---------------   _
//     /|\|           P1.0|-  |
//      | |           P1.1|-  | to stepper
//      --|RST        P1.2|-  |
//        |           P1.3|-  |
//        |               |  -
//        |           P1.4|- pulled down with switch to Vcc
//
//  Jacob Ward
//	Sept. 2011
//  Built with CCS Version 4.2.0
//******************************************************************************

#include <msp430g2231.h>

#define PERIOD (5000)
#define CLOSE (0)
#define OPEN (1)

int direction = CLOSE;											// state variable that holds the direction the motor should rotate in
int stop = 0;																// state variable that says when the motor should stop
int motorState = 1;													// holds the value of the stepper coils

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= ~(BIT6 + BIT5 + BIT4);           // P1.4, P1.5, P1.6 input
  
  P1OUT = 1;																// set up stepper motor driver
    
 	P1IES = 0x00;															// Port 1 interrups triggers on low to high transition
 	P1IE = BIT6 + BIT5 + BIT4;								// P1.4, P1.5, P1.6 interrupt enable
 	P1IFG = 0x00;															// clear port 1 interrupt flags
  
  TA0CCTL0 = CCIE;                          // CCR0 interrupt enabled
  TA0CCR0 = PERIOD;													// Load cap comp register with step period
  TA0CTL = TASSEL_2 + MC_2;                 // SMCLK, contmode
   
  if(P1IN & BIT4)														// if the register is closed...
  {													
  	stop = 1;																// don't try to close it
  	direction = OPEN;
  }
  	
  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
	if(stop)																	// if we shouldn't move...
	{
		P1OUT &= ~(0x0F);												// turn off all stepper coils
		return;
	}
	if(direction == OPEN)											// if we need to open...
	{
		motorState <<= 1;												// rotate one stop open
	  if(motorState > 8)
	  	motorState = 1;
	  P1OUT &= ~(0x0F);	  
	  P1OUT |= motorState;
	}
	else 
	{
		motorState >>= 1;												// otherwise we're closing
		if(motorState == 0)											// so close the motor one step
			motorState = 8;
	  P1OUT &= ~(0x0F);	  
	  P1OUT |= motorState;
	}
  TA0CCR0 += PERIOD;                        // Add Offset to CCR0
}

#pragma vector = PORT1_VECTOR
__interrupt void Port1(void)
{
	switch(P1IFG)
	{
		case BIT4:															// closed button has been hit
			if(direction == CLOSE)								// if we were in the closed state... (this is 'debouncing')
			{
				direction = OPEN;										// switch to opening
				stop = 1;														// and stop
			}
			break;
		case BIT5:															// open button has been hit
			if(direction == OPEN)									// if we were in the opened state...
			{
				direction = CLOSE;									// switch to closing
				stop = 1;														// and stop
			}
			break;
		case BIT6:															// toggle button has been hit
			stop = 0;															// so go
			break;
	}
	P1IFG = 0x00;															// clear the register flags
}
